package es.upv.tricia;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.util.Log;
import es.upv.tricia.Tricia.GameQuestions;
import es.upv.tricia.Tricia.Questions;

public class TriciaProvider extends ContentProvider
{
	private static final String TAG = "LocalQuestionProvider";

	private static final String DATABASE_NAME = "supertrivialgame.db";
	private final static String DATABASE_DIR = "/data/data/es.upv.tricia/databases/";
	private final static String DATABASE_PATH = DATABASE_DIR + DATABASE_NAME;
	private static final int DATABASE_VERSION = 1;
	private static final String QUESTIONS_TABLE_NAME = "questions";
	private static final String GAME_QUESTIONS_TABLE_NAME = "game_questions";

	private static final int QUESTIONS = 1;
	private static final int QUESTION = 2;

	private static UriMatcher sUriMatcher;
	private static HashMap<String, String> sQuestionProjectionMap;

	static {
		sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
		sUriMatcher.addURI(Tricia.AUTHORITY, "questions", QUESTIONS);
		sUriMatcher.addURI(Tricia.AUTHORITY, "questions/#", QUESTION);

		sQuestionProjectionMap = new HashMap<String, String>();
		sQuestionProjectionMap.put(GameQuestions._ID, GameQuestions._ID);
		sQuestionProjectionMap
				.put(GameQuestions.SUBJECT, GameQuestions.SUBJECT);
		sQuestionProjectionMap.put(GameQuestions.QUESTION_TEXT,
				GameQuestions.QUESTION_TEXT);
		sQuestionProjectionMap
				.put(GameQuestions.ANSWER1, GameQuestions.ANSWER1);
		sQuestionProjectionMap
				.put(GameQuestions.ANSWER2, GameQuestions.ANSWER2);
		sQuestionProjectionMap
				.put(GameQuestions.ANSWER3, GameQuestions.ANSWER3);
		sQuestionProjectionMap
				.put(GameQuestions.ANSWER4, GameQuestions.ANSWER4);
		sQuestionProjectionMap.put(GameQuestions.RIGHT_ANSWER,
				GameQuestions.RIGHT_ANSWER);
		sQuestionProjectionMap.put(GameQuestions.HELP, GameQuestions.HELP);
	}

	private static class DatabaseHelper extends SQLiteOpenHelper
	{
		private Context mContext;

		public DatabaseHelper(Context context)
		{
			super(context, DATABASE_NAME, null, DATABASE_VERSION);

			this.mContext = context;
		}

		private void initializeDatabase() throws SQLiteException
		{
			File file = new File(DATABASE_PATH);

			if (!file.exists()) {
				try {
					File dir = new File(DATABASE_DIR);

					if (!dir.exists()) {
						Log.i(TAG,
								"Creating directory " + dir.getAbsolutePath());
						dir.mkdirs();
					}

					Log.i(TAG, "Database does not exist. Copying template to "
							+ DATABASE_PATH);
					file.createNewFile();

					InputStream is = mContext.getAssets().open(DATABASE_NAME);
					OutputStream os = new FileOutputStream(file);

					// transfer bytes from the inputfile to the outputfile
					byte[] buffer = new byte[1024];
					int length;
					while ((length = is.read(buffer)) > 0) {
						os.write(buffer, 0, length);
					}

					// close the streams
					os.flush();
					os.close();
					is.close();
				} catch (IOException e) {
					throw new RuntimeException("Could not copy database", e);
				}
			}
		}

		@Override
		public synchronized SQLiteDatabase getReadableDatabase()
		{
			initializeDatabase();

			return super.getReadableDatabase();
		}

		@Override
		public synchronized SQLiteDatabase getWritableDatabase()
		{
			initializeDatabase();

			return super.getWritableDatabase();
		}

		@Override
		public void onCreate(SQLiteDatabase db)
		{
		}

		@Override
		public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
		{
		}
	}

	private DatabaseHelper mOpenHelper;

	@Override
	public boolean onCreate()
	{
		mOpenHelper = new DatabaseHelper(getContext());

		return true;
	}

	@Override
	public Cursor query(Uri uri, String[] projection, String selection,
			String[] selectionArgs, String sortOrder)
	{
		Cursor cursor;
		String limit = null;
		SQLiteDatabase db = mOpenHelper.getReadableDatabase();

		switch (sUriMatcher.match(uri)) {
		case QUESTIONS:
			break;

		case QUESTION:
			selection = GameQuestions._ID + "=?";
			selectionArgs = new String[] { uri.getPathSegments().get(1) };
			limit = "1";
			break;

		default:
			throw new IllegalArgumentException("Unknown URI " + uri);
		}

		SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
		qb.setTables(GAME_QUESTIONS_TABLE_NAME);
		qb.setProjectionMap(sQuestionProjectionMap);

		if (sortOrder == null) {
			sortOrder = GameQuestions._ID + " DESC";
		}

		cursor = qb.query(db, projection, selection, selectionArgs, null, null,
				sortOrder, limit);

		// Tell the cursor what uri to watch, so it knows when its source data
		// changes
		cursor.setNotificationUri(getContext().getContentResolver(), uri);

		return cursor;
	}

	@Override
	public String getType(Uri uri)
	{
		switch (sUriMatcher.match(uri)) {
		case QUESTIONS:
			return GameQuestions.CONTENT_TYPE;

		case QUESTION:
			return GameQuestions.CONTENT_ITEM_TYPE;

		default:
			throw new IllegalArgumentException("Unknown URI " + uri);
		}
	}

	@Override
	public Uri insert(Uri uri, ContentValues initialValues)
	{
		switch (sUriMatcher.match(uri)) {
		case QUESTIONS:
			SQLiteDatabase db = mOpenHelper.getReadableDatabase();
			db.delete(GAME_QUESTIONS_TABLE_NAME, null, null);

			// reset autoincrement sequence
			db.delete("sqlite_sequence", "name=?",
					new String[] { GAME_QUESTIONS_TABLE_NAME });

			String queriedColumns = Questions._ID + "," + Questions.SUBJECT
					+ "," + Questions.QUESTION_TEXT + "," + Questions.ANSWER1
					+ "," + Questions.ANSWER2 + "," + Questions.ANSWER3 + ","
					+ Questions.ANSWER4 + "," + Questions.RIGHT_ANSWER + ","
					+ Questions.HELP;
			String insertedColumns = GameQuestions.QUESTION_ID + ","
					+ GameQuestions.SUBJECT + "," + GameQuestions.QUESTION_TEXT
					+ "," + GameQuestions.ANSWER1 + "," + GameQuestions.ANSWER2
					+ "," + GameQuestions.ANSWER3 + "," + GameQuestions.ANSWER4
					+ "," + GameQuestions.RIGHT_ANSWER + ","
					+ GameQuestions.HELP;

			db.execSQL("INSERT INTO " + GAME_QUESTIONS_TABLE_NAME + "("
					+ insertedColumns + ") SELECT " + queriedColumns + " FROM "
					+ QUESTIONS_TABLE_NAME + " ORDER BY RANDOM()");

			break;

		default:
			throw new IllegalArgumentException("Unknown URI " + uri);
		}

		return uri;
	}

	@Override
	public int delete(Uri uri, String selection, String[] selectionArgs)
	{
		switch (sUriMatcher.match(uri)) {
		case QUESTIONS:
			SQLiteDatabase db = mOpenHelper.getReadableDatabase();

			// reset autoincrement sequence
			db.delete("sqlite_sequence", "name=?",
					new String[] { GAME_QUESTIONS_TABLE_NAME });

			return db.delete(GAME_QUESTIONS_TABLE_NAME, null, null);

		default:
			throw new IllegalArgumentException("Unknown URI " + uri);
		}
	}

	@Override
	public int update(Uri uri, ContentValues values, String selection,
			String[] selectionArgs)
	{
		throw new UnsupportedOperationException();
	}

}
